package com.sagframe.sagacity.sqltoy.plus.conditions.interfaces;

import com.sagframe.sagacity.sqltoy.plus.utils.ArrayUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

/**
 * 比较条件抽象接口
 * <p>比较值</p>
 *
 * @param <Children>
 * @param <R> 参与比较的字段
 */
public interface Compare<Children, R> extends Serializable {

    /**
     * ignore
     */
    default Children eq(R column, Object val) {
        return eq(true, column, val);
    }

    /**
     * 等于 =
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children eq(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children ne(R column, Object val) {
        return ne(true, column, val);
    }

    /**
     * 不等于 &lt;&gt;
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children ne(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children gt(R column, Object val) {
        return gt(true, column, val);
    }

    /**
     * 大于 &gt;
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children gt(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children ge(R column, Object val) {
        return ge(true, column, val);
    }

    /**
     * 大于等于 &gt;=
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children ge(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children lt(R column, Object val) {
        return lt(true, column, val);
    }

    /**
     * 小于 &lt;
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children lt(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children le(R column, Object val) {
        return le(true, column, val);
    }

    /**
     * 小于等于 &lt;=
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children le(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children between(R column, Object val1, Object val2) {
        return between(true, column, val1, val2);
    }

    /**
     * BETWEEN 值1 AND 值2
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val1      值1
     * @param val2      值2
     * @return children
     */
    Children between(boolean condition, R column, Object val1, Object val2);

    /**
     * ignore
     */
    default Children notBetween(R column, Object val1, Object val2) {
        return notBetween(true, column, val1, val2);
    }

    /**
     * NOT BETWEEN 值1 AND 值2
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val1      值1
     * @param val2      值2
     * @return children
     */
    Children notBetween(boolean condition, R column, Object val1, Object val2);

    /**
     * ignore
     */
    default Children like(R column, Object val) {
        return like(true, column, val);
    }

    /**
     * LIKE '%值%'
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children like(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children notLike(R column, Object val) {
        return notLike(true, column, val);
    }

    /**
     * NOT LIKE '%值%'
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children notLike(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children likeLeft(R column, Object val) {
        return likeLeft(true, column, val);
    }

    /**
     * LIKE '%值'
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children likeLeft(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children likeRight(R column, Object val) {
        return likeRight(true, column, val);
    }

    /**
     * LIKE '值%'
     *
     * @param condition 执行条件
     * @param column    字段
     * @param val       值
     * @return children
     */
    Children likeRight(boolean condition, R column, Object val);

    /**
     * ignore
     */
    default Children isNull(R column) {
        return isNull(true, column);
    }

    /**
     * 字段 IS NULL
     * <p>例: isNull("name")</p>
     *
     * @param condition 执行条件
     * @param column    字段
     * @return children
     */
    Children isNull(boolean condition, R column);

    /**
     * ignore
     */
    default Children isNotNull(R column) {
        return isNotNull(true, column);
    }

    /**
     * 字段 IS NOT NULL
     * <p>例: isNotNull("name")</p>
     *
     * @param condition 执行条件
     * @param column    字段
     * @return children
     */
    Children isNotNull(boolean condition, R column);

    /**
     * ignore
     */
    default Children in(R column, Collection<?> coll) {
        return in(true, column, coll);
    }

    /**
     * 字段 IN (value.get(0), value.get(1), ...)
     * <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
     *
     * <li> 注意！集合为空若存在逻辑错误，请在 condition 条件中判断 </li>
     * <li> 如果集合为 empty 则不会进行 sql 拼接 </li>
     *
     * @param condition 执行条件
     * @param column    字段
     * @param coll      数据集合
     * @return children
     */
    Children in(boolean condition, R column, Collection<?> coll);

    /**
     * ignore
     */
    default Children in(R column, Object... values) {
        return in(true, column, values);
    }

    /**
     * 字段 IN (v0, v1, ...)
     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
     *
     * <li> 注意！数组为空若存在逻辑错误，请在 condition 条件中判断 </li>
     * <li> 如果动态数组为 empty 则不会进行 sql 拼接 </li>
     *
     * @param condition 执行条件
     * @param column    字段
     * @param values    数据数组
     * @return children
     */
    Children in(boolean condition, R column, Object... values);

    /**
     * ignore
     */
    default Children inSql(R column, String sql, Map<String, Object> paramMap) {
        return inSql(true, column, sql, paramMap);
    }

    /**
     * ignore
     */
    default Children inSql(R column, String sql) {
        return inSql(true, column, sql, null);
    }

    /**
     * 字段 IN (v0, v1, ...)
     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
     *
     * <li> 注意！数组为空若存在逻辑错误，请在 condition 条件中判断 </li>
     * <li> 如果动态数组为 empty 则不会进行 sql 拼接 </li>
     *
     * @param condition 执行条件
     * @param sql    子查询sql
     * @param paramMap    子查询条件值
     * @return children
     */
    Children inSql(boolean condition, R column, String sql, Map<String, Object> paramMap);

    default Children inb(Collection<R> columns, Collection<Object[]> values) {
        return inb(true, columns, values);
    }

    /**
     * (字段1,字段2...) IN ((v0, v1...), (v2, v3...)...)
     * <p>例: in("id","code", Object[]...)</p>
     *
     * <li> 注意！数组为空若存在逻辑错误，请在 condition 条件中判断 </li>
     * <li> 如果动态数组为 empty 则不会进行 sql 拼接 </li>
     *
     * @param condition 执行条件
     * @param columns    字段集合
     * @param values    数据数组
     * @return children
     */
    Children inb(boolean condition, Collection<R> columns, Collection<Object[]> values);

    /**
     * ignore
     */
    default Children notIn(R column, Collection<?> coll) {
        return notIn(true, column, coll);
    }

    /**
     * 字段 NOT IN (value.get(0), value.get(1), ...)
     * <p>例: notIn("id", Arrays.asList(1, 2, 3, 4, 5))</p>
     *
     * @param condition 执行条件
     * @param column    字段
     * @param coll      数据集合
     * @return children
     */
    Children notIn(boolean condition, R column, Collection<?> coll);

    /**
     * ignore
     */
    default Children notIn(R column, Object... value) {
        return notIn(true, column, value);
    }

    /**
     * 字段 NOT IN (v0, v1, ...)
     * <p>例: notIn("id", 1, 2, 3, 4, 5)</p>
     *
     * @param condition 执行条件
     * @param column    字段
     * @param values    数据数组
     * @return children
     */
    Children notIn(boolean condition, R column, Object... values);

    /*******************************语法糖方法扩展*****************************/
    default Children likeIfPresent(R column, String val) {
        if (StringUtils.hasText(val)) {
            return like(true, column, val);
        }else{
            return like(false, column, val);
        }
    }

    default Children inIfPresent(R column, Collection<?> values) {
        if (!CollectionUtils.isEmpty(values)) {
            return in(true, column, values);
        }else{
            return in(false, column, values);
        }
    }

    default Children inIfPresent(R column, Object... values) {
        if (!ArrayUtils.isEmpty(values)) {
            return in(true, column, values);
        }else{
            return in(false, column, values);
        }
    }

    default Children eqIfPresent(R column, Object val) {
        if (val != null) {
            return eq(true, column, val);
        }else{
            return eq(false, column, val);
        }
    }

    default Children neIfPresent(R column, Object val) {
        if (val != null) {
            return ne(true, column, val);
        }else {
            return ne(false, column, val);
        }
    }


    default Children gtIfPresent(R column, Object val) {
        if (val != null) {
            return gt(true, column, val);
        }else{
            return gt(false, column, val);
        }
    }

    default Children geIfPresent(R column, Object val) {
        if (val != null) {
            return ge(true, column, val);
        }else {
            return ge(false, column, val);
        }
    }


    default Children ltIfPresent(R column, Object val) {
        if (val != null) {
            return lt(true, column, val);
        }else{
            return lt(false, column, val);
        }
    }


    default Children leIfPresent(R column, Object val) {
        if (val != null) {
            return le(true, column, val);
        }else{
            return le(false, column, val);
        }
    }

    default Children betweenIfPresent(R column, Object val1, Object val2) {
        if (val1 != null && val2 != null) {
            return between(true, column, val1, val2);
        }
        if (val1 != null) {
            return ge(true, column, val1);
        }else{
            if (val2 != null) {
                return le(true, column, val2);
            }else{
                return le(false, column, val2);
            }
        }

    }

    default Children betweenIfPresent(R column, Object[] values) {
        if (values == null) {
            return between(false, column, null, null);
        }
        if (values!= null && values.length > 1 && values[0] != null && values[1] != null) {
            return between(true, column, values[0], values[1]);
        }
        if (values!= null && values.length > 0 && values[0] != null) {
            return ge(true, column, values[0]);
        }else{
            if(values!= null && values.length > 1 && values[1] != null){
                return le(true, column, values[1]);
            }else{
                return le(false, column, values[1]);
            }
        }
    }
}
